﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using AForge.Imaging.Filters;
using WindowsFormsGUI.Entidades;

namespace WindowsFormsGUI
{
    public partial class Form1 : Form
    {
        private int _contador50;
        private int _contador25;
        private float[] arreglo1;
        private float[] arreglo2;
        private List<double> _minimos;

        public Form1()
        {
            InitializeComponent();
            _minimos = new List<double>();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Metodo1();
            //Metodo3();
            Metodo5();
        }

        private void Metodo5()
        {
            pictureBox1.Load(@"D:\img\25cC.jpg");
            var bitmap = new Bitmap(pictureBox1.Image);
            var imagenProcesada = ProcesarImagen(bitmap);
            arreglo1 = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(imagenProcesada);            
            pictureBox1.Image = Dibujar(arreglo1);

            pictureBox2.Load(@"D:\img\50cC.jpg");
            bitmap = new Bitmap(pictureBox2.Image);
            imagenProcesada = ProcesarImagen(bitmap);
            arreglo2 = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(imagenProcesada);
            pictureBox2.Image = Dibujar(arreglo2);

            for (int i = 0; i < 180; i++)
            {
                Metodo6(i * 2);
            }

            var valores = _minimos.OrderByDescending(dato => dato).Take(5);

            foreach (var val in valores)
            {
                label3.Text += "[" + val + "]";
            }
        }

        private void Metodo6(double angulo)
        {
            pictureBox3.Load(@"D:\img\50cC02.jpg");
            var bitmap = new Bitmap(pictureBox3.Image);
            var imagenProcesada = ProcesarImagen(bitmap, angulo);
            var arreglo = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(imagenProcesada);
            pictureBox3.Image = imagenProcesada;

            var d1 = CalcularDistanciaEuclidia(arreglo1, arreglo);
            var d2 = CalcularDistanciaEuclidia(arreglo2, arreglo);

            if (d1 > d2)
            {
                _contador25++;
                _minimos.Add(d2);                
            }

            if (d1 < d2)
            {
                _contador50++;
            }

            label1.Text = "Contador 25: " + _contador25;
            label2.Text = "Contador 50: " + _contador50;           
        }

        private void Metodo1()
        {
            pictureBox1.Load(@"D:\img\50A.jpg");
            var bitmap1 = new Bitmap(pictureBox1.Image);
            var redimension1 = Redimensionar(bitmap1);
            var gris1 = EscalaDeGrises(redimension1);
            var bina1 = Binarizacion(gris1);
            pictureBox1.Image = bina1;
            var arreglo1 = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(bina1);

            pictureBox2.Load(@"D:\img\25A.jpg");
            var bitmap2 = new Bitmap(pictureBox2.Image);
            var redimension2 = Redimensionar(bitmap2);
            var gris2 = EscalaDeGrises(redimension2);
            var bina2 = Binarizacion(gris2);
            pictureBox2.Image = bina2;
            var arreglo2 = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(bina2);

            pictureBox3.Load(@"D:\img\25cC.jpg");
            var bitmap3 = new Bitmap(pictureBox3.Image);
            var redimension3 = Redimensionar(bitmap3);
            var gris3 = EscalaDeGrises(redimension3);
            var bina3 = Binarizacion(gris3);
            pictureBox3.Image = bina3;
            var arreglo3 = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(bina3);

            var d1 = CalcularDistanciaEuclidia(arreglo1, arreglo3);
            var d2 = CalcularDistanciaEuclidia(arreglo2, arreglo3);

            label1.Text = "Distancia entre 50 y 25: " + d1;
            label2.Text = "Distancia entre 25 y 25: " + d2;

            pictureBox1.Image = HacerOREntre2Imagenes((Bitmap)pictureBox2.Image, (Bitmap)pictureBox3.Image);
        }

        private void Metodo3()
        {
            Metodo4();

            for (int i = 0; i < 180; i++)
            {
                Metodo2(i * 2);
            }
        }

        private void Metodo4()
        {
            pictureBox1.Load(@"D:\img\25cC.jpg");
            var bitmap = new Bitmap(pictureBox1.Image);
            var imagenProcesada = ProcesarImagen(bitmap);
            var arreglo = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(imagenProcesada);
            ProcesadorDeImagen.InicializarRed(arreglo.Length);
            ProcesadorDeImagen.Red.Train(arreglo);
            ProcesadorDeImagen.Agregar(new ImageMonedaRecordada(arreglo, CaraSecaEnum.VeinticincoCentavosCara));
            pictureBox1.Image = Dibujar(arreglo);

            pictureBox2.Load(@"D:\img\50cC.jpg");
            bitmap = new Bitmap(pictureBox2.Image);
            imagenProcesada = ProcesarImagen(bitmap);
            arreglo = ProcesadorDeImagen.ConvertirImagenEnArregloDeFloat(imagenProcesada);
            ProcesadorDeImagen.Red.Train(arreglo);
            ProcesadorDeImagen.Agregar(new ImageMonedaRecordada(arreglo, CaraSecaEnum.CincuentaCentavosCara));
            pictureBox2.Image = Dibujar(arreglo);
        }

        private void Metodo2(double angulo)
        {
            pictureBox3.Load(@"D:\img\25cC02.jpg");
            var bitmap = new Bitmap(pictureBox3.Image);
            var imagenProcesada = ProcesarImagen(bitmap, angulo);
            pictureBox3.Image = imagenProcesada;
            var moneda1 = ProcesadorDeImagen.Clasificar(imagenProcesada);

            if (moneda1.Denominacion == DenominacionEnum.VeinticincoCentavos)
            {
                _contador25++;
            }

            if (moneda1.Denominacion == DenominacionEnum.CincuentaCentavos)
            {
                _contador50++;
            }

            label1.Text = "Contador 25: " + _contador25;
            label2.Text = "Contador 50: " + _contador50;
            label3.Text = "La moneda es de: " + moneda1.Denominacion;
        }

        private Bitmap Rotar(Bitmap bitmap, double angulo)
        {
            // create filter - rotate for 30 degrees keeping original image size
            var filter = new RotateBilinear(angulo, true);
            // apply the filter
            return filter.Apply(bitmap);
        }

        private Bitmap Dibujar(float[] arreglo)
        {
            var bitmap = new Bitmap(100, 100);

            for (int i = 0; i < 100; i++)
            {
                for (int j = 0; j < 100; j++)
                {
                    if (arreglo[i + j * 100] == 1)
                    {
                        bitmap.SetPixel(i, j, Color.White);
                    }
                    else
                    {
                        bitmap.SetPixel(i, j, Color.Black);
                    }
                }
            }

            return bitmap;
        }

        private Bitmap ProcesarImagen(Bitmap bitmap)
        {
            return ProcesarImagen(bitmap, 0);
        }

        private Bitmap ProcesarImagen(Bitmap bitmap, double angulo)
        {
            var redimension = Redimensionar(bitmap);
            var gris = EscalaDeGrises(redimension);
            var rotar = Rotar(gris, angulo);
            var binarizacion = Binarizacion(rotar);

            return binarizacion;
        }

        private Bitmap EscalaDeGrises(Bitmap bitmap)
        {
            var filtro = new Grayscale(0.2125, 0.7154, 0.0721);
            return filtro.Apply(bitmap);
        }

        public Bitmap Binarizacion(Bitmap bitmap)
        {
            var filtro = new Threshold();
            return filtro.Apply(bitmap);
        }

        private Bitmap Redimensionar(Bitmap bitmap)
        {
            var filtro = new ResizeNearestNeighbor(100, 100);
            return filtro.Apply(bitmap);
        }

        private double CalcularDistanciaEuclidia(float[] monedaRecordada, float[] arreglo)
        {
            double acumulador = 0;

            for (int i = 0; i < monedaRecordada.Length; i++)
            {
                acumulador += Math.Pow((monedaRecordada[i] - arreglo[i]), 2);
            }

            return Math.Sqrt(acumulador);
        }

        private Bitmap HacerOREntre2Imagenes(Bitmap imagen1, Bitmap imagen2)
        {
            var salida = new Bitmap(imagen1.Width, imagen1.Height);

            for (int i = 0; i < imagen1.Height; i++)
            {
                for (int j = 0; j < imagen1.Width; j++)
                {
                    var p1 = imagen1.GetPixel(i, j);
                    var p2 = imagen2.GetPixel(i, j);

                    if (p1 == p2)
                    {
                        salida.SetPixel(i, j, Color.Black);
                    }
                    else
                    {
                        salida.SetPixel(i, j, Color.White);
                    }
                }
            }

            return salida;
        }
    }
}
